
(define (flatmap proc seq)
    (define (accumulate op initial sequence)
        (if (null? sequence)
            initial
            (op 
                (car sequence)
                (accumulate op initial (cdr sequence))
            )
        )
    )
    (accumulate append `() (map proc seq))
)

(define (enumerate-interval low height)
    (if (> low height)
        `()
        (cons low (enumerate-interval (+ low 1) height))
    )
)


(define (prime? n)
    (define (smallest-divisor n)
        (find-divisor n 2)
    )
    (define (find-divisor n test-divisor)
        (cond ((> (* test-divisor test-divisor) n) n)
            ((dividers? test-divisor n) test-divisor)
            (else (find-divisor n (next test-divisor )))
        )
    )

    (define (next test-divisor)
        (if (= 2 test-divisor)
            3
            (+ test-divisor 2)
        )
    )
    (define (dividers? a b)
        (= (remainder b a) 0)
    )
    (= n (smallest-divisor n))
)

(define (prime-sum? pair)
    (prime? (+ (car pair) (cadr pair)))
)

(define (make-pair-sum pair)
    (list (car pair) (cdr pair) (+ (car pair) (cadr pair)))
)

(define (prime-sum-pairs n)
    (map 
        make-pair-sum
        (filter 
            prime-sum?
            (flatmap
                (lambda (i) 
                    (map
                        (lambda (j)                            
                            (list i j)
                        )
                        (enumerate-interval 1 (- i 1)) 
                    )
                )
                (enumerate-interval 1 n)
            )
        ) 
    )
)


(display (prime-sum-pairs 6))
(newline)


(define (unique-pairs n)
    (define (check-pair? pair)
        (> (car pair) (cadr pair))
    )
    (filter 
        check-pair?
        (flatmap
                (lambda (i) 
                    (map
                        (lambda (j)                            
                            (list i j)
                        )
                        (enumerate-interval 1 (- i 1)) 
                    )
                )
                (enumerate-interval 1 n)
            
        )
    )   
)
(define (prime-sum-pairs2 n)
    (map 
        make-pair-sum
        (filter 
            prime-sum?
            (unique-pairs n)
        ) 
    )
)
(display (prime-sum-pairs2 6))
(exit)